﻿#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include <ctype.h>
#include<assert.h>

#include"vld.h"      //检测是否释放完全

/*
	结构体.的优先级较高  高于解引用*

	int atoi(const char* str)

	atoi  作用是把对应字符串转换成为整数  
	注意：1.从字符串开始处进行解析数字字符  直到遇到第一个非数字字符（空格  制表符  换行符等）或者字符串结束符 \0为止
		  2.忽略前导空白字符（空格  制表符  换行符等）
		  3.若字符串第一个非空白字符不是数字字符或者正负号   atoi返回0
		  4.字符串中含正负号  atoi返回对应正负数
		  5.字符串表示的数字超过int范围  atoi的行为就是未定义的 大于最大返回最大  小于最小返回最小   可能返回INT_MAX或者INT_MIN 或者导致其他错误行为

	#define  没有类型检查

	malloc函数申请的空间不初始化，calloc函数申请的空间会被初始化为0    双参数

	free是可以释放NULL的   参数可以为NULL

	局部变量函数运行结束后   程序会回收内存

	fgetc是适用于所有输入流字符输入函数
	getchar是标准输入流
	fputs是适用于所有输出流的文本行输出函数
	fread是适用于文件输入流的二进制输入函数
*/

//模拟实现atoi函数（把字符串转化为整数）     并非自我实现
//#include <stdio.h>
//#include <ctype.h>
//int my_atoi(const char* str) {
//    int result = 0;
//    int sign = 1;
//    int i = 0;
//    // 跳过前导空格
//    while (isspace(str[i])) {      //isspace判断是否为空格或者制表符等
//        i++;
//    }
//    // 处理符号
//    if (str[i] == '+' || str[i] == '-') {
//        sign = (str[i] == '-') ? -1 : 1;
//        i++;
//    }
//    // 处理数字部分
//    while (isdigit(str[i])) {     //isdigit判断数字是否十进制数作为循环条件（是返回非0  不是返回0） 
//        int digit = str[i] - '0';
//        result = result * 10 + digit;
//        i++;
//    }
//    return result * sign;
//}
//
//int main() {
//    const char* test_str = "   -12b45";
//    int num = my_atoi(test_str);
//    printf("The integer value is: %d\n", num);
//    return 0;
//}

//int my_atoi(const char* str)
//{
//	//先定义要用的内容
//	int result = 0;   //最终结果
//	int sign = 1;     //符号正负
//	int i = 0;		
//	//对空格进行判断
//	while (isspace (str[i]))    //isspace  是判断是否为空格/制表符等 的函数
//	{
//		i++;
//	}
//	//判断符号
//	if(str[i]=='+'||str[i]=='-')
//	{
//		sign = (str[i] == '-') ? -1 : 1;
//		i++;
//	}
//	//对数字进行判断
//	while (isdigit(str[i]))
//	{
//		result = result * 10 + str[i] - '0';
//		i++;
//	}
//	return result * sign;
//}
//
//int main()
//{
//	char str[] = "   -668a89ap99";
//	int num = my_atoi(str);
//	printf("最终结果是：%d\n",num);
//	return 0;
//}

//模拟实现二
//定义枚举  列举正常转换和非正常转化
//enum State
//{
//	VAILD,    //合法  正常
//	INVAILD   //非法  非正常
//}state=INVAILD;     //定义一个变量并赋一个初值  
//
//int my_atoi(const char* str)
//{
//	//加上断言  防止为空指针
//	assert(str != NULL); 
//	//若本身就就是一个\0为空串  返回0
//	if (*str == '\0')
//	{
//		return 0;
//	}
//	//判断是否为空格   运用isspace  是空格返回非0  否则为0  
//	while (isspace(*str))
//	{
//		str++;
//	}
//	//到此  str一定不是空格
//	int flag = 1;
//	if (*str == '+')
//	{
//		flag = 1;
//		str++;
//	}
//	else if(*str=='-')
//	{
//		flag = -1;
//		str++;
//	}
//	//把字符串中所有字符全部判断
//	int ret = 0;      //存储结果
//	while (*str != '\0')
//	{
//		//是数字字符  isdigit 是数字字符返回值不为0
//		if (isdigit(*str))
//		{
//			//数字字符变为数字
//			//int ret=*str - '0';
//
//			ret = ret * 10 + (*str - '0') * flag;
//			//得到超出范围  那就返回最大或者最小值
//			if (ret > INT_MAX)
//			{
//				ret = INT_MAX;
//			}
//			if(ret<INT_MIN)
//			{
//				ret = INT_MIN;
//			}
//		}
//		//不是数字字符
//		else
//		{
//			return ret;
//		}
//		str++;     //每一次if后都要++
//	}
//	//此处加入判断是否为结尾  如果是就置为合法
//	if (*str == '\0')
//	{
//		state = VAILD;
//	}
//
//	return ret;
//}
//
//int main()
//{
//	char str[] = "   -2586a4";
//	int ret = my_atoi(str);
//	printf("%d\n", ret);
//	if (state == VAILD)
//	{
//		printf("合法转化：%d\n", ret);
//	}
//	else
//	{
//		printf("非法转化：%d\n", ret);
//	}
//	return 0;
//}


//练习
//int main()
//{
//	unsigned char puc[4];
//	struct tagPIM
//	{
//		unsigned char ucPim1;
//		unsigned char ucData0 : 1;    //位段
//		unsigned char ucData1 : 2;
//		unsigned char ucData2 : 3;
//	}*pstPimData;
//	pstPimData = (struct tagPIM*)puc;
//	memset(puc, 0, 4);    //数组全部置0
//	pstPimData->ucPim1 = 2;    //赋值  0000 0010
//	pstPimData->ucData0 = 3;   //      0000 0011   虽然八个比特位  但是实际只有1个位段  也就只会存储一个1  
//	pstPimData->ucData1 = 4;   //同理  0000 0100   存入00
//	pstPimData->ucData2 = 5;   //      0000 0101   存入101
// 最终会在第二个字节处存放  后三个位段的内容并存储    也就是      101  00  1（因为不足八个bit位   故要进行补齐  也就是00 101 00 1）    后面两个字节没有使用到
//	printf("%02x %02x %02x %02x\n", puc[0], puc[1], puc[2], puc[3]);     //输出 02  29  00  00 （%02x   以16进制输出）
//	return 0;
//}

//练习（pointer分配几个字节空间？）
//#define MAX_SIZE A+B
//struct _Record_Struct
//{
//	unsigned char Env_Alarm_ID : 4;  
//	unsigned char Para1 : 2;
// 到这是6个bit位  占一个字节  
//	unsigned char state;
// 单独一个字节
//	unsigned char avail : 1;
// 独立一个又一个字节
//}*Env_Alarm_Record;
//struct _Record_Struct* pointer = (struct _Record_Struct*)malloc(sizeof(struct _Record_Struct) * MAX_SIZE);
//注意：MAX_SIZE  是2+3  也就是前面的数*2+3  也就是3*2+3   也就是9字节   若加上括号就是5*3+3=18（替换也就是直接换不能带括号）


//练习
//union Un
//{
//	short s[7];
//	int n;
//};
//int main()
//{
//	printf("%zd\n", sizeof(union Un));   //输出16   因为联合体是共用空间  前面的数组是14   空间大小应该是为  int的整数倍   即16
//	return 0;
//}

//小端存  0x11223344 -->存储为44 33 22 11     打印也就是11 22 33 44 进行打印
//							  低      高址    高地址向低地址打印（高数据先打印  低数据后打印）
//练习
//int main()
//{
//	union   //联合体内存为2字节
//	{
//		short k;
//		char i[2];
//	}*s, a;
//	s = &a;
//	s->i[0] = 0x39;    //低地址到高地址进行存储   低地址存低数据  高地址存高数据   打印是高地址向低地址打印
//	s->i[1] = 0x38;
//	printf("%x\n", a.k);    //输出3839
//	return 0;
//}

//练习
//struct student
//{
//	int num;
//	char name[32];
//	float score;
//}stu;
//struct student 是用户定义的结构体类型
//stu 是用户定义的结构体变量名


//把任意的数字，从中间拆分成两个数字，比如1461 可以拆分成（1和461）, （14和61）, （146和1), 如果所有拆分后的乘积之和等于自身，则是一个Lily Number。
//例如：
//655 = 6 * 55 + 65 * 5
//1461 = 1 * 461 + 14 * 61 + 146 * 1
//求出 5位数中的所有 Lily Number（变种水仙花）
//int weishu(int i,int count)
//{
//	while (i)
//	{
//		i /= 10;
//		count++;
//	}
//	return count;
//}
//
////i%10 == 个位     i/10=前面的各位     循环一次10*10  
//int pan(int i)
//{
//	//处理位数
//	int count = 0;
//	int wei = weishu(i,count);
//	int dd = 10;   //dd用来记录操作数
//	int result = 0;  //记录结果
//	int left = 0;
//	int right = 0;
//	//进行  位数-1  次运算
//	for (; (wei - 1) > 0; wei--)
//	{
//		left = i / dd;
//		right = i % dd;
//		result += left * right;
//		dd *= 10;
//	}
//	if(result==i)
//	return 1;
// else
// return -1;
//}
//
//int main()
//{
//	for (int i = 10000; i <= 99999; i++)
//	{
//		int ret=pan(i);
//		if (ret== 1)
//		{
//			printf("%d  ", i);
//		}
//	}
//	return 0;
//}

//上题的精简
//int main()
//{
//	for (int i = 10000; i <= 99999; i++)
//	{
//		int sum = 0;
//		for (int j = 10; j <= 10000; j *= 10)
//		{
//			sum += (i / j) * (i % j);
//		}
//		if (sum == i)
//		{
//			printf("%d ", i);
//		}
//	}
//	return 0;
//}

//(*注意*非自我完成*)
//有一个整数序列（可能有重复的整数），现删除指定的某一个整数，输出删除指定数字之后的序列，序列中未被删除数字的前后位置没有发生改变。
//数据范围：序列长度和序列中的值都满足    1≤n≤50
//输入：第一行输入一个整数(0≤N≤50)。
//第二行输入N个整数，输入用空格分隔的N个整数。
//第三行输入想要进行删除的一个整数。
//输出:一行，删除指定数字之后的序列。
// （先处理输入  后进行处理）
// 
//int main()
//{
//	int n = 0;   //a存储几个整数
//	scanf("%d\n", &n);  //输入的第一行整数  也就是几个数
//	int arr[50] = { 0 };
//	for (int i = 0; i < n; i++)
//	{
//		scanf("%d ", &arr[i]);   //输入的第二行整数  整条数组
//	}
//	int del;   //定义删除数字
//	scanf("%d", &del);   //输入要删除的数字
//	int i = 0;
//	int j = 0;
//	//定义两个下标  和del不同就往后走   相同一个不动一个往后  然后进行后把前一个覆盖
//	for (; i < n; i++)
//	{
//		if (arr[i] != del)
//		{
//			arr[j] = arr[i];
//			j++;
//		}
//	}
//	//进行输出
//	for (int k = 0; k < j; k++)
//	{
//		printf("%d ",arr[k]);
//	}
//
//	return 0;
//}


//使用联合体判断大小端
//union cc
//{
//	char ch;
//	int i;
//}pp;
//
//int check()
//{
//	pp.i = 1;
//	return pp.ch;
//}
//
//int main()
//{
//	int ret = check();
//	if (ret == 1)
//	{
//		printf("小端");
//	}
//	else
//	{
//		printf("大端");
//	}
//	return 0;
//}

/*
(*非自我完成*)
LeetCode（数组串联）
Note: The returned array must be malloced, assume caller calls free().    //必须为malloc进行开辟
nums:当前数组   numsSize：当前数组的长度    returnSize返回的数组的长度
 */

//int* getConcatenation(int* nums, int numsSize, int* returnSize)   //参数一个数组  一个数组大小  一个返回数组的大小
//{
//	int* ans = (int*)malloc(sizeof(int) * numsSize * 2);
//	//ans[i]=nums[i]        ans[i+n]=nums[i]     n为数组长度3
//	for (int i = 0; i < numsSize; i++)
//	{
//		ans[i] = nums[i];
//		ans[i + numsSize] = nums[i];
//	}
//	*returnSize = 2 * numsSize;
//	return ans;
//}
//int main()
//{
//	int arr[] = { 1,2,1 };
//	int returnSize = 0;
//	int* p = getConcatenation(arr, 3, &returnSize);
//	for(int i=0;i<returnSize;i++)
//	{ 
//	printf("%d ", *(p + i));
//	}
//	return 0;
//}


//使用malloc函数模拟开辟一个3*5的整型二维数组，开辟好后，使用二维数组的下标访问形式，访问空间。
//int main()
//{
//	int* p = (int*)malloc(3 * 5 * sizeof(int));
//	int arr[3][5] = { 0 };
//	int* ptr = arr;
//	if (p == NULL)
//	{
//		perror("malloc");
//		return 1;
//	}
//	for (int i = 0; i < 3*5; i++)
//	{
//		*(p + i) = i+1;
//		*(ptr + i) = *(p + i);
//	}
//
//	for (int i = 0; i < 3; i++)
//	{
//		for (int j = 0; j < 5; j++)
//		{
//			printf("%d ", arr[i][j]);
//		}
//	}
//
//	return 0;
//}

//上题（参考）
//int main()
//{
//	int* p = (int*)malloc(sizeof(int*) * 5);   //开一维数组   连续5个整型
//	if (p == NULL)
//	{
//		return 1;
//	}
//	//二维数组每一个元素都是一个一维数组  开二维数组   用malloc开辟的时候  malloc(3*sizeof(in*))   每一个元素都是int*
//	int** arr = (int**)malloc(sizeof(int*) * 3);    //int**   每一块地址都是存储的int*   三个一维数组  存储的都是int*类型   故应该用int**进行存储
//	if (arr == NULL)
//	{
//		return 1;
//	}
//	for (int i = 0; i < 3; i++)
//	{
//		arr[i] = (int*)malloc(5 * sizeof(int));	
//		//进行赋值   malloc 开辟空间都是随机值
//		for (int j = 0; j < 5; j++)
//		{
//			arr[i][j] = 1;
//		}
//	}
//
//	//进行打印
//	for (int i = 0; i < 3; i++)
//	{
//		for (int j = 0; j < 5; j++)
//		{
//			printf("%d ", arr[i][j]);
//		}
//		printf("\n");
//	}
//
////不进行释放   用上 vld.h 就会出现四个内存泄漏提示(每个都会提示报错)
// for(int i=0;i<3;i++)
// {
//		free(arr[i]);
//		arr[i]=NULL;       //每一块都要进行free
// }
//
//	free(arr);
//	arr = NULL;
//
//
//	return 0;
//}




//写一个程序拷贝文件
//使用所学文件操作，在当前目录下放一个文件data.txt，写一个程序，将data.txt文件拷贝一份，生成data_copy.txt文件。
//思路：
//打开文件data.txt，读取数据，打开文件data_copy.txt，写数据
//从data.txt中读取数据存放到data_copy.txt文件中，直到文件结束。关闭两个文件
//int main()
//{
//	FILE* ps = fopen("data.txt", "w");
//	if (ps == NULL)
//	{
//		perror("fopen");
//		return 1;
//	}
//	FILE* pf = fopen("data_copy.txt", "w");
//	if (pf == NULL)
//	{
//		perror("fopen");
//		return 1;
//	}
//	//往data.txt写内容
//	//fputs("hello lichangxian\n", ps);
//	//fputs("fighting lichangxian\n", ps);
//	//fputs("great lichangxian\n", ps);
//
//	fclose(ps);
//	ps = NULL;
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}
//
//
//int main()
//{
//	FILE* ps = fopen("data.txt", "r");
//	if (ps == NULL)
//	{
//		perror("fopen");
//		return 1;
//	}
//	FILE* pf = fopen("data_copy.txt", "w");
//	if (pf == NULL)
//	{
//		perror("fopen");
//		return 1;
//	}
//	char arr[25] = { 0 };
//	while (fgets(arr, 25, ps) != NULL)
//	{
//		fputs(arr, pf);
//		printf("%s\n", arr);
//	}
//	fclose(ps);
//	ps = NULL;
//	fclose(pf);
//	pf = NULL;
//
//	return 0;
//}


//正确思路（方法）
/*注意  是为正确写法*/
//void CopyTxt()
//{
//	FILE* fr = fopen("data.txt", "r");
//	if (fr == NULL)
//	{
//		perror("fopen");
//		return;
//	}
//	FILE* fw = fopen("data_copy.txt", "w");
//	if (fw == NULL)
//	{
//		perror("fopen");
//		return;
//	}
//	//开始一边读一边写    拷贝
//	int ch = 0;
//	while ((ch = fgetc(fr) != EOF))
//	{
//		fputc(ch, fw);
//	}
//	fclose(fr);
//	fclose(fw);
//	fr = NULL;
//	fw = NULL;
//}
//
//int main()
//{
//	CopyTxt();
//	return 0;
//}
